package plus.easydo.starter.oauth.server.configure;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import plus.easydo.starter.oauth.server.handler.MyLogoutSuccessHandler;
import plus.easydo.starter.oauth.server.properties.Oauth2ServerProperties;

import javax.annotation.Resource;
import java.util.List;


/**
 * Security配置类
 *
 * @author yuzhanfeng
 */

@Order(90)
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Qualifier
    @Resource
    private ServerBeanConfig serverBeanConfig;

    @Value("${security.oauth2.whitelist}")
    private List<String> whiteList;

    /**
     * 需要实现自定义登录验证流程
     */
    @Resource
    private UserDetailsService userDetailsService;

    /**
     * 将AuthenticationManager 注入IoC容器
     *
     * @return AuthenticationManager
     * @throws Exception e
     */
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        Oauth2ServerProperties properties =  serverBeanConfig.properties();
        http
                /*关闭csrf 不使用session*/
                .csrf().disable()
                .authorizeRequests()
                /*放行OAuth2的自定义页面路径 不然http配置不生效 自定义页面如果不配置全局允许，浏览器会提示服务器将页面转发多次*/
                .antMatchers(properties.getLoginPath(), "/auth/authorize", "/oauth/authorize")
                .permitAll()
                /*放行配置文件中的路径数组*/
                /*放行静态资源*/
                .antMatchers(
                        HttpMethod.GET,
                        "/static/**",
                        "/*.html",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js"
                ).permitAll()
                /*放行白名单*/
                .antMatchers(whiteList.stream().distinct().toArray(String[]::new)).permitAll()
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated()
                .and()
                // 表单登录
                .formLogin()
                // 自定义登录页面请求路径
                .loginPage(properties.getLoginPath())
                // 登录处理url
                .loginProcessingUrl("/auth/authorize")
                .and()
                .logout()
                /*退出成功自定义返回*/
                .logoutSuccessHandler(new MyLogoutSuccessHandler())
                /*退出登录url*/
                .logoutUrl("/logout");
        http.httpBasic().disable();
    }


    /**
     * 设置登录服务、 密码编码验证器
     * @param auth AuthenticationManagerBuilder
     * @throws Exception e
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(serverBeanConfig.getPasswordEncoder());
    }


}
